﻿using System;
using System.Text;
using DMS.BaseClass;
using System.Collections;
using System.IO;
using System.Net;
using System.Xml;

namespace DMS.BaseClass
{
    public class FileUploader
    {
        #region 数据成员
        private readonly string _targetUrl = string.Empty;
        private readonly string _account = string.Empty;
        private readonly string _password = string.Empty;
        #endregion

        #region 构造函数
        private FileUploader()
        {
        }

        public FileUploader(string fileSerer, string account, string password)
        {
            this._targetUrl = fileSerer;
            this._account = account;
            this._password = password;
        }
        #endregion

        public string GetFileUrl(string filePath)
        {
            if (filePath.StartsWith("http", StringComparison.CurrentCultureIgnoreCase))
            {
                return filePath;
            }

            int index = filePath.IndexOf(@":\");
            if (index != -1)
            {
                return (this._targetUrl + "/" + filePath.Substring(index + 2).Replace(@"\", "/"));
            }
            return (this._targetUrl + "/" + filePath.Replace(@"\", "/"));
        }

        public void PrepareWebDirectory(string targetURL)
        {
            Stack stack = new Stack();
            Uri uri = new Uri(targetURL);
            string format = "http://{0}:{1}";
            StringBuilder builder = new StringBuilder(string.Format(format, uri.Host, uri.Port));
            foreach (string str2 in uri.Segments)
            {
                builder.Append(str2);
                if (str2.EndsWith("/"))
                {
                    stack.Push(builder.ToString());
                }
            }
            Stack stack2 = new Stack();
            string targetUrl = stack.Pop().ToString();
            while (!this.WebFileDirectoryExist(targetUrl))
            {
                stack2.Push(targetUrl);
                if (stack.Count == 0)
                {
                    throw new Exception("没有找到文件服务器。");
                }
                targetUrl = stack.Pop().ToString();
            }
            while (0 < stack2.Count)
            {
                targetUrl = stack2.Pop().ToString();
                this.WebDavOperate(targetUrl, "MKCOL");
            }
        }

        public SortedList GetDirectoryContents(string url, int deep)
        {
            StreamReader reader;
            HttpWebRequest request = this.GetWebRequest(url);
            request.Headers.Add("Translate: f");
            string s = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><a:propfind xmlns:a=\"DAV:\"><a:prop><a:displayname/><a:iscollection/><a:getlastmodified/></a:prop></a:propfind>";
            request.Method = "PROPFIND";
            if (-1 == deep)
            {
                request.Headers.Add("Depth: infinity");
            }
            else
            {
                request.Headers.Add(string.Format("Depth: {0}", deep));
            }
            request.ContentLength = s.Length;
            request.ContentType = "text/xml";
            Stream requestStream = request.GetRequestStream();
            requestStream.Write(Encoding.ASCII.GetBytes(s), 0, Encoding.ASCII.GetBytes(s).Length);
            requestStream.Close();
            try
            {
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                reader = new StreamReader(response.GetResponseStream());
            }
            catch (WebException exception)
            {
                throw exception;
            }
            StringBuilder builder = new StringBuilder();
            char[] buffer = new char[0x400];
            int charCount = 0;
            for (charCount = reader.Read(buffer, 0, 0x400); charCount > 0; charCount = reader.Read(buffer, 0, 0x400))
            {
                builder.Append(buffer, 0, charCount);
            }
            reader.Close();
            XmlDocument document = new XmlDocument();
            document.LoadXml(builder.ToString());
            XmlNamespaceManager nsmgr = new XmlNamespaceManager(document.NameTable);
            nsmgr.AddNamespace("a", "DAV:");
            XmlNodeList list = document.SelectNodes("//a:prop/a:displayname", nsmgr);
            XmlNodeList list2 = document.SelectNodes("//a:prop/a:iscollection", nsmgr);
            XmlNodeList list3 = document.SelectNodes("//a:prop/a:getlastmodified", nsmgr);
            XmlNodeList list4 = document.SelectNodes("//a:href", nsmgr);
            SortedList list5 = new SortedList();
            for (int i = 0; i < list.Count; i++)
            {
                if (list4[i].InnerText.ToLower().TrimEnd(new char[] { '/' }) != url.ToLower().TrimEnd(new char[] { '/' }))
                {
                    FileItem resource = new FileItem();
                    resource.Name = list[i].InnerText;
                    resource.IsFolder = Convert.ToBoolean(Convert.ToInt32(list2[i].InnerText));
                    resource.Url = list4[i].InnerText;
                    resource.LastModified = Convert.ToDateTime(list3[i].InnerText);
                    list5.Add(resource.Url, resource);
                }
            }
            return list5;
        }

        public void UploadFileWithoutPrepareDirectory(Stream stream, string targetUrl)
        {
            Stream stream2 = null;
            BinaryReader reader = null;
            try
            {
                WebClient client = new WebClient();

                if (!string.IsNullOrEmpty(this._account))
                {
                    client.Credentials = new NetworkCredential(this._account, this._password);
                }

                stream2 = client.OpenWrite(targetUrl, "PUT");

                byte[] buffer = new byte[0x1000];
                reader = new BinaryReader(stream);
                for (int i = reader.Read(buffer, 0, 0x1000); i > 0; i = reader.Read(buffer, 0, 0x1000))
                {
                    stream2.Write(buffer, 0, i);
                }
            }
            finally
            {
                if (stream2 != null)
                {
                    stream2.Close();
                }
                if (reader != null)
                {
                    reader.Close();
                }
            }
        }

        public void WebDavOperate(string targetURL, string method)
        {
            HttpWebRequest request = this.GetWebRequest(targetURL);
            request.Headers.Add("Translate: f");
            request.Method = method;
            try
            {
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            }
            catch (WebException exception)
            {
                throw exception;
            }
        }

        public bool WebFileDirectoryExist(string targetUrl)
        {
            try
            {
                this.GetDirectoryContents(targetUrl, 0);
            }
            catch (WebException exception)
            {
                HttpWebResponse response = (HttpWebResponse)exception.Response;
                if (HttpStatusCode.NotFound != response.StatusCode)
                {
                    throw exception;
                }
                return false;
            }
            return true;
        }

        public HttpWebRequest GetWebRequest(string targetUrl)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(targetUrl);

            request.Credentials = CredentialCache.DefaultCredentials;
            if (!string.IsNullOrEmpty(this._account))
            {
                request.Credentials = new NetworkCredential(this._account, this._password);
            }

            return request;
        }
    }
}
